from django.conf import settings
from django.core.files.storage import Storage
from django.utils.deconstruct import deconstructible
from fdfs_client.client import Fdfs_client


@deconstructible
class FastDFSStorage(Storage):
    def __init__(self, base_url=None, client_conf=None):
        """初始化  是由django去做的 所以是无参的
         初始化的时机 是第一次文件上传 或者显示图片的链接的时候去创建  而且创建后不再创建
           :param base_url:用于构造图片完整路径使用,图片服务器的域名
           :param client_conf:FastDFS客户端配置文件的路径
           """
        if base_url is None:
            base_url = settings.FDFS_URL
        self.base_url = base_url
        if client_conf is None:
            client_conf = settings.FDFS_CLIENT_CONF
        self.client_conf = client_conf

    def _open(self, name, mode='rb'):
        """用不到打开文件  省略"""
        pass

    def _save(self, name, content):
        """
        在FastDFS中保存文件   每次上传都会调用
        :param name: 传入的文件名
        :param content: 文件内容
        :return: 保存到数据库中的FastDFS的文件名
        """
        # 生成客户端对象  django的文件系统在执行上传文件的操作时,保存文件会调用save方法
        # 在admin站上传文件的时候  调用的是这里的upload_by_buffer,在源代码中获取文件后缀的时候
        # 就获取不到  因为上传到storage里文件名没有后缀  所以在这里加上后缀名,而且要取切割后下标为-1的
        # 的部分 来表示后缀
        client = Fdfs_client(self.client_conf)
        ret = client.upload_by_buffer(content.read(), file_ext_name=name.split('.')[-1])
        if ret.get('Status') != 'Upload successed.':
            raise Exception('upload file failed')
        file_name = ret.get('Remote file_id')
        return file_name

    def url(self, name):
        """返回文件的完整url路径
        :param name:数据库中保存的文件名
        :return :完整的url
        """
        return self.base_url + name

    def exists(self, name):
        """
        判断文件是否存在，FastDFS可以自行解决文件的重名问题
        所以此处返回False，告诉Django上传的都是新文件
        :param name:  文件名
        :return: False
        """
        return False
